#include "network.h"
#include "logger.h"

#include <sys/stat.h>
#include <sys/types.h>

int initServer(Server_t *server, const ServerConfig_t *config)
{
    if (server == NULL)
    {
        PRINT_ERROR("failed to init server");
        LOG_ERROR("initServer", "failed to init server");
        return -1;
    }
    strcpy(server->ip, config->ip);
    server->port = config->port;

    server->addr.sin_family = AF_INET;
    server->addr.sin_addr.s_addr = inet_addr(config->ip);
    server->addr.sin_port = htons(config->port);
    server->addr_len = sizeof(server->addr);

    server->socket_fd = -1;
    server->max_connections = config->max_connections;

    server->if_reuse = 1;

    chdir(config->storage_path); // 修改工作目录到服务器存储文件的目录

    char cwd[1024];
    LOG_DEBUG("Network", "Server PWD: %s", getcwd(cwd, sizeof(cwd)));

    return 0;
}

int initTcpSocket(Server_t *server)
{
    server->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server->socket_fd == -1)
    {
        LOG_ERROR("Network", "Failed to create new socket");
        return -1;
    }

    if (server->if_reuse)
    {
        setsockopt(server->socket_fd, SOL_SOCKET, SO_REUSEADDR, &server->if_reuse, sizeof(server->if_reuse));
    }

    if (bind(server->socket_fd, (struct sockaddr *)&server->addr, sizeof(server->addr)) == -1)
    {
        LOG_ERROR("Network", "Failed to bind to %s on %d: %s",
                  server->ip, server->port, strerror(errno));
        return -1;
    }

    listen(server->socket_fd, server->max_connections);
    PRINT_INFO("Server %s listening to %d connectios on port %d",
               server->ip, server->max_connections, server->port);
    LOG_INFO("Network", "Server %s listening to %d connectios on port %d",
             server->ip, server->max_connections, server->port);

    return 0;
}

ClientList_t *initClientList(int max_clients)
{
    ClientList_t *client_list = MALLOC(ClientList_t, 1);
    if (client_list == NULL)
    {
        PRINT_ERROR("failed to malloc ClientList");
        return NULL;
    }

    client_list->clients = CALLOC(Client_t, max_clients); // 参数较多，用calloc保险
    if (client_list->clients == NULL)
    {
        PRINT_ERROR("failed to malloc Client");
        free(client_list);
        return NULL;
    }

    for (int i = 0; i < max_clients; i++)
    {
        client_list->clients[i].socket_fd = -1;             // 全部置为-1标记位
        strcpy(client_list->clients[i].user_info.pwd, "."); // 工作目录设为当前路径
    }
    client_list->count = 0;
    client_list->max_clients = max_clients;

    return client_list;
}

void freeClientList(ClientList_t *client_list)
{
    if (client_list != NULL)
    {
        free(client_list->clients);
        free(client_list);
    }
}

int acceptConnection(Server_t *server, Client_t *client)
{
    client->addr_len = sizeof(client->addr);
    client->socket_fd = accept(server->socket_fd, (struct sockaddr *)&client->addr, &client->addr_len);
    if (client->socket_fd == -1)
    {
        PRINT_ERROR("accept failed");
        LOG_ERROR("Network", "accept failed");
        return -1;
    }

    strcpy(client->ip, inet_ntoa(client->addr.sin_addr));
    client->port = ntohs(client->addr.sin_port);

    client->last_active_time = time(NULL);

    PRINT_INFO("Client connected: %s:%d", client->ip, client->port);
    LOG_INFO("Network", "Client connected: %s:%d", client->ip, client->port);


    return 0;
}

int acceptTunnelConnection(Tunnel_t *tunnel, Client_t *client)
{
    //client->addr_len = sizeof(client->addr);
    client->tunnel_fd = accept(tunnel->socket_fd, (struct sockaddr *)&client->addr, &client->addr_len);
    if (client->tunnel_fd == -1)
    {
        PRINT_ERROR("accept failed");
        LOG_ERROR("Network", "accept failed");
        return -1;
    }

    /* strcpy(client->ip, inet_ntoa(client->addr.sin_addr));
    client->port = ntohs(client->addr.sin_port); */

    client->last_active_time = time(NULL);

    PRINT_INFO("Client connected to tunnel: %s:%d", client->ip, client->port);
    LOG_INFO("Network", "Client connected to tunnel: %s:%d", client->ip, client->port);


    return 0;
}

void closeConnection(Client_t *client)
{
    close(client->socket_fd);
    close(client->tunnel_fd);
    client->socket_fd = -1;
    client->tunnel_fd = -1;
    PRINT_INFO("Close connection to %s:%d", client->ip, client->port);
    LOG_INFO("Network", "close connection to %s:%d", client->ip, client->port);
}

void updateActiveTime(Client_t *client)
{
    client->last_active_time = time(NULL);
}

ssize_t sendAll(int sockfd, const void *buffer, size_t length, int flags)
{
    size_t total_sent = 0;                  // 记录已经发送的字节数
    const char *buf = (const char *)buffer; // 传参使用 void* 避免发生类型转化，且复用性更强

    while (total_sent < length)
    {
        ssize_t bytes_sent = send(sockfd, buf + total_sent, length - total_sent, flags);
        if (bytes_sent == -1) // 如果发送失败返回 -1
        {
            if (errno == EINTR) // EINTR 表示系统调用被信号中断
            {
                continue; // 重试
            }
            else
            {
                return -1; // 其他错误返回 -1
            }
        }
        total_sent += bytes_sent; // 更新以及发送的自己数
    }

    return total_sent; // 返回总共发送的字节数
}

ssize_t recvAll(int sockfd, void *buffer, size_t length, int flags)
{
    size_t total_received = 0;
    char *buf = (char *)buffer;

    while (total_received < length)
    {
        ssize_t bytes_received = recv(sockfd, buf + total_received, length - total_received, flags);
        if (bytes_received == -1)
        {
            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                return -1;
            }
        }
        else if (bytes_received == 0)
        {
            break; // 连接关闭
        }
        total_received += bytes_received;
    }

    return total_received;
}

static int createTunnel(Tunnel_t *tunnel, const ServerConfig_t *config)
{
    if (tunnel == NULL)
    {
        PRINT_ERROR("failed to create tunnel");
        LOG_ERROR("Network", "failed to create tunnel");
        return -1;
    }

    for (int i = 0; i < config->tunnel_count; i++)
    {
        strcpy(tunnel->ip, config->tunnels->ip);
        tunnel->port = config->tunnels[i].port;

        tunnel->addr.sin_family = AF_INET;
        tunnel->addr.sin_addr.s_addr = inet_addr(config->tunnels->ip);
        tunnel->addr.sin_port = htons(config->tunnels[i].port);
        tunnel->addr_len = sizeof(tunnel->addr);

        tunnel->socket_fd = -1;
        tunnel->max_connections = config->max_connections;

        tunnel->if_reuse = 1;

        initTcpSocket(tunnel);
    }

    return 0;
}

ServerCluster_t *initServerCluster(const ServerConfig_t *config)
{
    ServerCluster_t *cluster = CALLOC(ServerCluster_t, 1);
    initServer(&cluster->server, config);
    initTcpSocket(&cluster->server);
    // 申请指定数量的隧道内存空间
    cluster->tunnel = CALLOC(Tunnel_t, config->tunnel_count);

    createTunnel(cluster->tunnel, config);

    return cluster;
}

void freeServerCluster(ServerCluster_t *cluster)
{
    // 释放隧道数组的内存
    if (cluster->tunnel)
    {
        free(cluster->tunnel);
    }

    // 释放ServerCluster_t结构体的内存
    free(cluster);
}